SPB Git forge

spb/rareindex

Public
54commits 1branches 0releases
7.1 MBsize
maindefault branch
10 days agolast push
TypeScript 61.9% HTML 37.2% SQL 0.7%
2.4 KB · 34 lines tsx
Raw Blame History
1import Link from 'next/link';2import { notFound } from 'next/navigation';3import { requireAdmin } from '@/lib/admin/auth';4import { rawRecordDetail } from '@/lib/admin/queries';5import { AdminShell, fmtTs } from '@/components/admin/shell';6import { Json } from '@/components/admin/connector-bits';78/** "View last payload" (SPEC §29): the immutable raw capture with its provenance (engine, parser/connector versions, snapshot ref). */9export default async function RawRecordPage({ params }: { params: Promise<{ id: string; rawId: string }> }) {10  await requireAdmin();11  const { id, rawId } = await params;12  const r = await rawRecordDetail(rawId);13  if (!r || String(r.connector_id) !== id) notFound();14  const payload = r.payload as Record<string, unknown> | null;15  const snapshot = payload && typeof payload === 'object' && typeof payload.snapshot === 'string' ? (payload.snapshot as string) : null;16  const rest = snapshot && payload ? Object.fromEntries(Object.entries(payload).filter(([k]) => k !== 'snapshot')) : payload;17  return (18    <AdminShell current="/admin/connectors" title={`Raw payload ${rawId}`} subtitle={<><Link href={`/admin/connectors/${id}`} className="underline">{id}</Link> · {String(r.kind)} · engine {String(r.engine)} · HTTP {String(r.http_status ?? '—')} · fetched {fmtTs(r.fetched_at)} · parser v{String(r.parser_version)} · connector v{String(r.connector_version)} · run {String(r.run_id ?? '—')}</>}>19      <div className="mb-3 text-xs text-muted">20        <a href={String(r.url)} target="_blank" rel="noreferrer noopener" className="underline">{String(r.url)}</a> · external id <span className="font-mono">{String(r.external_id ?? '—')}</span> · hash <span className="font-mono">{String(r.content_hash).slice(0, 16)}…</span>21        {r.snapshot_ref ? <> · snapshot on disk: <span className="font-mono">{String(r.snapshot_ref)}</span></> : null}22        {r.process_error ? <div className="mt-1 text-loss">process error: {String(r.process_error)}</div> : <div className="mt-1 text-subtle">{r.processed_at ? `normalised ${fmtTs(r.processed_at)}` : 'not yet normalised'}</div>}23      </div>24      <Json value={rest} />25      {snapshot ? (26        <details className="mt-4 text-xs">27          <summary className="cursor-pointer text-subtle">inline snapshot ({snapshot.length.toLocaleString()} chars)</summary>28          <Json value={snapshot.slice(0, 200_000)} className="mt-2" />29        </details>30      ) : null}31    </AdminShell>32  );33}34